package com.ruoyi.orderEat.service.impl;

import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.OssUtil;
import com.ruoyi.common.utils.RedisUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.websocket.WebSocketServer;
import com.ruoyi.orderEat.domain.ShopCart;
import com.ruoyi.orderEat.domain.ShopFlavour;
import com.ruoyi.orderEat.domain.ShopInfo;
import com.ruoyi.orderEat.domain.ShopInfoVO;
import com.ruoyi.orderEat.mapper.ShopFlavourMapper;
import com.ruoyi.orderEat.mapper.ShopInfoMapper;
import com.ruoyi.orderEat.service.IShopInfoService;
import com.ruoyi.orderEat.web.SaleStateCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品信息Service业务层处理
 *
 * @author DingHao
 * @date 2023-11-22
 */
@Service
public class ShopInfoServiceImpl implements IShopInfoService {
    @Autowired
    private ShopInfoMapper shopInfoMapper;

    @Autowired
    private ShopFlavourMapper shopFlavourMapper;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 查询商品信息
     *
     * @param shopId 商品信息主键
     * @return 商品信息
     */
    @Override
    public ShopInfo selectShopInfoByShopId(Long shopId) {
        return shopInfoMapper.selectShopInfoByShopId(shopId);
    }

    @Override
    public ShopInfoVO selectWxShopInfoByShopId(Long shopId) {
        return shopInfoMapper.selectWxShopInfoByShopId(shopId);
    }

    /**
     * 查询商品信息列表
     *
     * @param shopInfo 商品信息
     * @return 商品信息
     */
    @Override
    public PageInfo<ShopInfoVO> selectShopInfoList(ShopInfo shopInfo) {
        List<ShopInfoVO> shopInfos = shopInfoMapper.selectShopInfoList(shopInfo);
        shopInfos.forEach(item -> {
            item.setShopStatusName(SaleStateCode.getDesc(Integer.parseInt(item.getShopStatus())));
        });
        return new PageInfo<>(shopInfos);
    }

    /**
     * 新增商品信息
     *
     * @param shopInfo 商品信息
     * @return 结果
     */
    @Override
    public int insertShopInfo(ShopInfo shopInfo) {
        Long userId = SecurityUtils.getUserId();
        shopInfo.setCreateBy(String.valueOf(userId));
        shopInfo.setCreateTime(DateUtils.getNowDate());
        return shopInfoMapper.insertShopInfo(shopInfo);
    }

    /**
     * 修改商品信息
     *
     * @param shopInfo 商品信息
     * @return 结果
     */
    @Override
    public int updateShopInfo(ShopInfo shopInfo) {
        shopInfo.setUpdateTime(DateUtils.getNowDate());
        return shopInfoMapper.updateShopInfo(shopInfo);
    }

    /**
     * 批量删除商品信息
     *
     * @param shopIds 需要删除的商品信息主键
     * @return 结果
     */
    @Override
    public int deleteShopInfoByShopIds(Long[] shopIds) {
        Arrays.asList(shopIds).parallelStream().forEach(item -> {
            ShopInfo shopInfo = shopInfoMapper.selectShopInfoByShopId(item);
            String objectName = shopInfo.getShopUrl().substring(1);
            OssUtil.deleteOss(objectName);
        });
        return shopInfoMapper.deleteShopInfoByShopIds(shopIds);
    }

    /**
     * 删除商品信息信息
     *
     * @param shopId 商品信息主键
     * @return 结果
     */
    @Override
    public int deleteShopInfoByShopId(Long shopId) {
        ShopInfo shopInfo = shopInfoMapper.selectShopInfoByShopId(shopId);
        String objectName = shopInfo.getShopUrl().substring(1);
        OssUtil.deleteOss(objectName);
        return shopInfoMapper.deleteShopInfoByShopId(shopId);
    }

    @Override
    public void addCart(ShopCart shopCart) {
        String sign = "increase";
        toShopping(shopCart, sign);
    }

    @Override
    public void saveCartShopBatch(ShopCart shopCart) {
        String sign = "batchIncrease";
        toShopping(shopCart, sign);
    }

    private void toShopping(ShopCart shopCart, String sign) {
        Long shopId = shopCart.getShopId();
        Integer tableId = shopCart.getTableId();
        String listKey = CART_SHOP + tableId;
        StringBuilder flavourNames = new StringBuilder();
        StringBuilder cartIds = new StringBuilder(String.valueOf(shopId));
        StringBuilder markIds = new StringBuilder(String.valueOf(shopId));
        List<String> specificationAndFlavourIds = shopCart.getSpecificationAndFlavourIds();
        if (specificationAndFlavourIds!=null && specificationAndFlavourIds.size() > 0) {
            List<Long> flavourIds = specificationAndFlavourIds.parallelStream().map(item -> {
                String[] ids = item.split("-");
                String id = ids[1];
                return Long.parseLong(id);
            }).collect(Collectors.toList());
            for (int i = 0; i < flavourIds.size(); i++) {
                Long flavourId = flavourIds.get(i);
                ShopFlavour shopFlavour = shopFlavourMapper.selectShopFlavourByFlavourId(flavourId);
                String flavourName = shopFlavour.getFlavourName();
                if (i > 0) {
                    flavourNames.append("、");
                }
                // 添加flavourName
                flavourNames.append(flavourName);
                cartIds.append(flavourId);
                markIds.append("-"+flavourId);
            }
            String key = CART_SHOP + tableId + ":" + cartIds.toString();
            Boolean hasKey = redisUtil.hasKey(key);
            if (hasKey) {
                if (sign.equals("increase")) {
                    redisUtil.hIncrBy(key, "shopNum", 1);
                } else {
                    redisUtil.hIncrBy(key, "shopNum", shopCart.getShopNum());
                }
            } else {
                redisUtil.hPut(key, "cartId", Long.parseLong(cartIds.toString()));
                redisUtil.hPut(key, "shopId", shopId);
                redisUtil.hPut(key, "shopName", shopCart.getShopName());
                redisUtil.hPut(key, "shopPic", shopCart.getShopPic());
                redisUtil.hPut(key, "flavourName", flavourNames.toString());
                redisUtil.hPut(key, "markId", markIds.toString());
                redisUtil.hPut(key, "shopNum", shopCart.getShopNum());
                redisUtil.hPut(key, "shopAmount", shopCart.getShopAmount());
                redisUtil.lRightPush(listKey, Long.parseLong(cartIds.toString()));
            }
            Integer shopNum = (Integer) redisUtil.hGet(key, "shopNum");
            ShopCart newShopCart = new ShopCart();
            newShopCart.setShopId(shopId);
            newShopCart.setShopNum(shopNum);
            newShopCart.setTableId(tableId);
            newShopCart.setDecreaseItem(0);
            String shopCartString = JSON.toJSONString(newShopCart);
            // 通知前端
            try {
                WebSocketServer.sendInfo(shopCartString, null);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }else {
            String key = CART_SHOP + tableId + ":" + shopId;
            Boolean hasKey = redisUtil.hasKey(key);
            if (hasKey) {
                if (sign.equals("increase")) {
                    redisUtil.hIncrBy(key, "shopNum", 1);
                } else {
                    redisUtil.hIncrBy(key, "shopNum", shopCart.getShopNum());
                }
            } else {
                redisUtil.hPut(key, "cartId", shopId);
                redisUtil.hPut(key, "shopId", shopId);
                redisUtil.hPut(key, "shopName", shopCart.getShopName());
                redisUtil.hPut(key, "shopPic", shopCart.getShopPic());
                redisUtil.hPut(key, "shopNum", shopCart.getShopNum());
                redisUtil.hPut(key, "shopAmount", shopCart.getShopAmount());
                redisUtil.lRightPush(listKey, shopId);
            }
            Integer shopNum = (Integer) redisUtil.hGet(key, "shopNum");
            ShopCart newShopCart = new ShopCart();
            newShopCart.setShopId(shopId);
            newShopCart.setShopNum(shopNum);
            newShopCart.setTableId(tableId);
            //newShopCart.setDecreaseItem(0);
            String shopCartString = JSON.toJSONString(newShopCart);
            // 通知前端
            try {
                WebSocketServer.sendInfo(shopCartString, null);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void addToCart(String key, String flavourName) {

    }

    @Override
    public void delCart(ShopCart shopCart) {
        String cartId = shopCart.getCartId();
        Long shopId = shopCart.getShopId();
        ShopInfo shopInfo = shopInfoMapper.selectShopInfoByShopId(shopId);
        Integer minimumQuantity = shopInfo.getMinimumQuantity();
        if (cartId==null || cartId.isEmpty()){
            cartId = String.valueOf(shopId);
        }
        Integer tableId = shopCart.getTableId();
        String key = CART_SHOP + tableId + ":" + cartId;
        String listKey = CART_SHOP + tableId;
        if (redisUtil.hGet(key, "shopNum") == null) {
            throw new ServiceException("没有此商品", HttpStatus.BAD_REQUEST);
        }
        Integer shopNum = (Integer) redisUtil.hGet(key, "shopNum");
        if (shopNum > 1 ) {
            if (minimumQuantity>0 && shopNum.equals(minimumQuantity)){
                redisUtil.hIncrBy(key, "shopNum", -minimumQuantity);
            }else {
                redisUtil.hIncrBy(key, "shopNum", -1);
            }
            shopNum = (Integer) redisUtil.hGet(key, "shopNum");
            if (shopNum==0){
                redisUtil.delete(key);
                redisUtil.lRemove(listKey, 1, Long.parseLong(cartId));
            }
        } else {
            redisUtil.delete(key);
            redisUtil.lRemove(listKey, 1, Long.parseLong(cartId));
            shopNum = 0;
        }
        ShopCart newShopCart = new ShopCart();
        newShopCart.setShopId(shopId);
        newShopCart.setShopNum(shopNum);
        newShopCart.setTableId(tableId);
        newShopCart.setDecreaseItem(1);
        String shopCartString = JSON.toJSONString(newShopCart);
        // 通知前端
        try {
            WebSocketServer.sendInfo(shopCartString, null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void delAllCart(List<ShopCart> shopCartList, Integer tableId) {
        String listKey = CART_SHOP + tableId;
        List<String> cartIds = shopCartList.stream().map(ShopCart::getCartId).collect(Collectors.toList());
        for (String cartId : cartIds) {
            String key = CART_SHOP + tableId + ":" + cartId;
            redisUtil.delete(key);
        }
        redisUtil.delete(listKey);
        // 通知前端
        try {
            WebSocketServer.sendInfo("delCart", null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public List<ShopCart> shopCartList(Integer tableId) {
        String listKey = CART_SHOP + tableId;
        List<String> cartIds = JSON.parseArray(JSON.toJSONString(redisUtil.lRange(listKey, 0, -1)), String.class);
        List<ShopCart> shopCartList = cartIds.stream().map(item -> {
            ShopCart shopCart = new ShopCart();
            String cartKey = listKey + ":" + item;
            Map<Object, Object> shoptMap = redisUtil.hGetAll(cartKey);
            shopCart.setCartId(item);
            shopCart.setShopId((Long) shoptMap.get("shopId"));
            shopCart.setShopName((String) shoptMap.get("shopName"));
            shopCart.setFlavourName((String) shoptMap.get("flavourName"));
            shopCart.setMarkId((String) shoptMap.get("markId"));
            shopCart.setShopPic((String) shoptMap.get("shopPic"));
            shopCart.setShopNum((Integer) shoptMap.get("shopNum"));
            BigDecimal amount = new BigDecimal(JSON.toJSONString(shoptMap.get("shopAmount")));
            shopCart.setShopAmount(amount);
            BigDecimal saleAmount = amount.multiply(new BigDecimal(JSON.toJSONString(shoptMap.get("shopNum"))));
            shopCart.setSaleAmount(saleAmount);
            return shopCart;
        }).collect(Collectors.toList());
        return shopCartList;
    }

    @Override
    public String saleAmountCount(Integer tableId) {
        String listKey = CART_SHOP + tableId;
        List<Long> shopIds = JSON.parseArray(JSON.toJSONString(redisUtil.lRange(listKey, 0, -1)), Long.class);
        /**
         * reduce 方法用于将所有商品的销售额累加起来。这里初始值为 BigDecimal.ZERO，使用 BigDecimal::add 来累加每个元素
         * **/
        BigDecimal allSale = shopIds.stream().map(item -> {
            Integer shopNum = (Integer) redisUtil.hGet(listKey + ":" + item, "shopNum");
            BigDecimal amount = new BigDecimal(JSON.toJSONString(redisUtil.hGet(listKey + ":" + item, "shopAmount")));
            return amount.multiply(new BigDecimal(shopNum));
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
        return allSale.toString();
    }

    @Override
    public String getCartCount(Integer tableId) {
        String listKey = CART_SHOP + tableId;
        List<Long> shopIds = JSON.parseArray(JSON.toJSONString(redisUtil.lRange(listKey, 0, -1)), Long.class);
        Integer shopNum = shopIds.stream().map(item -> (Integer) redisUtil.hGet(listKey + ":" + item, "shopNum")).reduce(0, Integer::sum);
        return String.valueOf(shopNum);
    }


}
